package com.zlsy.springbootdemo.encryption.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import java.io.IOException;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;

public class JacksonJsonMapper {

  public static ObjectMapper objectMapper = new ObjectMapper();

  static {
    objectMapper =
        new ObjectMapper()
            .findAndRegisterModules()
            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    // 忽略 在json字符串中存在，但是在java对象中不存在对应属性的情况。防止错误
    objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    // 忽略空Bean转json的错误
    objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    // 在序列化时，只有那些值为null或被认为为空的值的属性才不会被包含在内。
    objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
    // 接受单个字符的值反序列化为数组。
    objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
  }

  public static Map toMap(String json) {
    try {
      return objectMapper.readValue(json, Map.class);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public static <K, V> Map<K, V> toMap(String json, Type type) {
    TypeReference<Map<K, V>> typeReference =
        new TypeReference<Map<K, V>>() {
          @Override
          public Type getType() {
            return type;
          }
        };
    try {
      return (Map<K, V>) objectMapper.readValue(json, typeReference);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public static List toList(String json) {
    try {
      return objectMapper.readValue(json, List.class);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public static <T> List<T> toList(String json, Type type) {
    TypeReference<List<T>> typeReference =
        new TypeReference<List<T>>() {
          @Override
          public Type getType() {
            return type;
          }
        };
    try {
      return (List<T>) objectMapper.readValue(json, typeReference);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public static String toJsonString(Object object) {
    try {
      return objectMapper.writeValueAsString(object);
    } catch (JsonProcessingException e) {
      throw new RuntimeException(e);
    }
  }

  public static String toJsonString(Object object, String dateFormatPattern) {
    SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatPattern);
    try {
      return objectMapper.writer(dateFormat).writeValueAsString(object);
    } catch (JsonProcessingException e) {
      throw new RuntimeException(e);
    }
  }

  public static <T> T toObject(String json, Class<T> valueType) {
    try {
      return objectMapper.readValue(json, valueType);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public static <K, V> Map<K, V> objectToMap(Object fromValue) {
    return objectMapper.convertValue(fromValue, Map.class);
  }

  public static <T> T mapToObject(Map fromMap, Class<T> toValueType) {
    return objectMapper.convertValue(fromMap, toValueType);
  }
}
